<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>MapLibre + deck.gl 渲染大量多边形</title>
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
    <script src="https://unpkg.com/maplibre-gl@3.3.1/dist/maplibre-gl.js"></script>
    <link href="https://unpkg.com/maplibre-gl@3.3.1/dist/maplibre-gl.css" rel="stylesheet" />
    <script src="https://unpkg.com/deck.gl@8.9.33/dist.min.js"></script>
    <style>
        body {
            margin: 0;
            padding: 0;
        }

        #map {
            position: absolute;
            top: 0;
            bottom: 0;
            width: 100%;
        }

        .controls {
            position: absolute;
            top: 10px;
            right: 10px;
            background: white;
            padding: 10px;
            border-radius: 5px;
            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
            font-family: Arial, sans-serif;
            font-size: 12px;
        }

        .legend {
            position: absolute;
            bottom: 20px;
            left: 20px;
            background: white;
            padding: 10px;
            border-radius: 5px;
            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
            font-family: Arial, sans-serif;
            font-size: 12px;
        }
    </style>
</head>

<body>
    <div id="map"></div>
    <div class="controls">
        <button id="add-polygons">添加10,000个多边形</button>
        <div id="polygon-count">当前多边形数量: 0</div>
    </div>
    <div class="legend">
        <h3>土地类型</h3>
        <div>
            <div style="display: inline-block; width: 12px; height: 12px; background: rgba(34, 139, 34, 0.7);"></div> 森林
        </div>
        <div>
            <div style="display: inline-block; width: 12px; height: 12px; background: rgba(255, 218, 185, 0.7);"></div>
            耕地
        </div>
        <div>
            <div style="display: inline-block; width: 12px; height: 12px; background: rgba(135, 206, 235, 0.7);"></div>
            水域
        </div>
        <div>
            <div style="display: inline-block; width: 12px; height: 12px; background: rgba(220, 220, 220, 0.7);"></div>
            城市
        </div>
    </div>

    <script>
        // 天地图API密钥（替换为你自己的）
        const TIANDITU_KEY = "24f053f3d41f3e2df373d25ed9d8fef7";

        // 存储所有多边形数据
        let allPolygons = [];
        let polygonCount = 0;

        // 初始化MapLibre地图
        const map = new maplibregl.Map({
            container: 'map',
            style: {
                version: 8,
                name: '天地图影像',
                sources: {
                    'tdt-img': {
                        type: 'raster',
                        tiles: [
                            `https://t0.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${TIANDITU_KEY}`
                        ],
                        tileSize: 256,
                        attribution: '<a href="https://www.tianditu.gov.cn" target="_blank">天地图</a>'
                    }
                },
                layers: [{
                    id: 'tdt-img-layer',
                    type: 'raster',
                    source: 'tdt-img',
                    minzoom: 0,
                    maxzoom: 18
                }]
            },
            center: [116.3956, 39.9152], // 北京
            zoom: 9
        });

        // 等待地图加载完成
        map.on('load', () => {
            // 创建空的多边形图层
            const {
                SolidPolygonLayer
            } = window.deck;
            const {
                MapLibreLayer
            } = window.deck;

            let polygonLayer = new deck.SolidPolygonLayer({
                id: 'polygon-layer',
                data: allPolygons,
                pickable: true,
                stroked: true,
                filled: true,
                wireframe: true,
                lineWidthMinPixels: 1,
                getPolygon: d => d.coordinates,
                getFillColor: d => d.color,
                getLineColor: [0, 0, 0, 100],
                getLineWidth: 1,
                // 优化：使用GPU加速数据处理
                fp64: false,
                // 优化：设置透明度以启用深度测试
                opacity: 0.7,
                // 优化：只渲染可见区域内的多边形
                autoHighlight: true,
                highlightColor: [255, 255, 255, 128],
                // 优化：使用WebGL实例化技术
                instanceCount: allPolygons.length
            });

            // 创建MapLibreLayer并添加到地图
            const deckLayer = new deck.MapboxOverlay({
                id: 'deck-layer',
                // deckLayers: [polygonLayer],
                layers: [polygonLayer],
                map: map
            });
            
            map.addControl(deckLayer);
            // map.addLayer(deckLayer);
            // map.addControl(new maplibregl.NavigationControl());

            // 添加交互：点击显示多边形信息
            map.on('click', 'deck-layer', (e) => {
                if (e.features && e.features.length > 0) {
                    const feature = e.features[0];
                    new maplibregl.Popup()
                        .setLngLat(e.lngLat)
                        .setHTML(`
              <div><strong>ID:</strong> ${feature.properties.id}</div>
              <div><strong>类型:</strong> ${feature.properties.type}</div>
              <div><strong>面积:</strong> ${feature.properties.area.toFixed(2)} km²</div>
            `)
                        .addTo(map);
                }
            });

            // 添加多边形按钮事件
            document.getElementById('add-polygons').addEventListener('click', () => {
                // 生成10,000个随机多边形
                const newPolygons = generateRandomPolygons(10000, polygonCount);
                allPolygons = [...allPolygons, ...newPolygons];
                console.log('allPolygons', allPolygons);
                polygonCount += 10000;

                // 更新计数显示
                document.getElementById('polygon-count').textContent =
                    `当前多边形数量: ${polygonCount.toLocaleString()}`;

                // 更新图层数据
                polygonLayer = polygonLayer.clone({
                    data: allPolygons,
                    instanceCount: allPolygons.length
                });

                deckLayer.setProps({
                    layers: [polygonLayer]
                });
            });
        });

        // 生成随机多边形数据
        function generateRandomPolygons(count, startId) {
            const polygons = [];
            const landTypes = [{
                    name: '森林',
                    color: [34, 139, 34, 180]
                }, // 绿色
                {
                    name: '耕地',
                    color: [255, 218, 185, 180]
                }, // 浅橙色
                {
                    name: '水域',
                    color: [135, 206, 235, 180]
                }, // 浅蓝色
                {
                    name: '城市',
                    color: [220, 220, 220, 180]
                } // 浅灰色
            ];

            for (let i = 0; i < count; i++) {
                const id = startId + i;
                const centerLng = 116.1 + Math.random() * 0.6; // 经度范围
                const centerLat = 39.7 + Math.random() * 0.6; // 纬度范围
                const radius = 0.001 + Math.random() * 0.005; // 多边形大小
                const pointCount = 3 + Math.floor(Math.random() * 7); // 3-9个顶点

                // 生成随机多边形顶点
                const points = [];
                for (let j = 0; j < pointCount; j++) {
                    const angle = (j / pointCount) * Math.PI * 2;
                    const dx = Math.cos(angle) * radius * (0.8 + Math.random() * 0.4);
                    const dy = Math.sin(angle) * radius * (0.8 + Math.random() * 0.4);
                    points.push([centerLng + dx, centerLat + dy]);
                }

                // 计算近似面积（简化版）
                const area = radius * radius * Math.PI * 100; // 转换为km²

                // 随机选择土地类型
                const typeIndex = Math.floor(Math.random() * landTypes.length);
                const type = landTypes[typeIndex];

                polygons.push({
                    id,
                    coordinates: [points], // 外层数组表示环（Ring）
                    properties: {
                        id,
                        type: type.name,
                        area
                    },
                    color: type.color
                });
            }

            return polygons;
        }
    </script>
</body>

</html>